package com.ysstech.finance.thread;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

import com.googlecode.aviator.AviatorEvaluator;
import com.ysstech.common.util.BigDecimalUtil;
import com.ysstech.common.util.DateUtil;
import com.ysstech.common.util.function.FunctionAdd;
import com.ysstech.finance.entity.*;
import com.ysstech.finance.enums.FinanceAuxEnum;
import com.ysstech.finance.service.SubjectAdjustAuxilaryService;
import com.ysstech.finance.service.VoucherService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.util.CollectionUtils;

@Slf4j
public class VoucherSaveThread implements Callable<T> {
    private Voucher voucher;
    private List<Object> voucherList;
    private List<VoucherTemplate> listTemplate;
    private VoucherService voucherService;
    private SubjectAdjustAuxilaryService subjectAdjustAuxilaryService;

    public VoucherSaveThread(List<Object> voucherList, List<VoucherTemplate> listTemplate,
                             Voucher voucher, VoucherService voucherService, SubjectAdjustAuxilaryService subjectAdjustAuxilaryService) {
        this.voucherList = voucherList;
        this.listTemplate = listTemplate;
        this.voucherService = voucherService;
        this.voucher = voucher;
        this.subjectAdjustAuxilaryService = subjectAdjustAuxilaryService;
    }

    @Override
    public T call() throws Exception {
        AviatorEvaluator.addFunction(new FunctionAdd());
        List<Voucher> addList = new ArrayList<>();
        log.info(DateUtil.dateToStrByFormat(new Date(), "yyyy-MM-dd HH:mm:ss:SSS") + voucher.getAccountId());
        //循环每一条数据，一条数据一个凭证
        for (Iterator<Object> iterator = voucherList.iterator(); iterator.hasNext(); ) {
            Object vo = iterator.next();
            if (null == vo) {
                continue;
            }
            Map<String, Object> mapData = getDataMap(vo); //获取一条数据的值
            String num = DateUtil.generateNumber();
            for (VoucherTemplate template : listTemplate) {
                if (null == template) {
                    continue;
                }
                voucher.setNum(num);
                if (2 == template.getIsLoop()) {
                    Voucher newVoucher = this.getVoucher(template, mapData, voucher);
                    if (null == newVoucher) {
                        continue;
                    }
                    addList.add(newVoucher);
                    continue;
                }
                if (1 == template.getIsLoop()) {
                   /* List<VoucherVo> list = vo.getListLoop();
                    for (VoucherVo voucherVo : list) {
                        Map<String, Object> mapDat2 = this.getDataMap(voucherVo);
                        Voucher newVoucher = this.getVoucher(template, mapDat2, voucher);
                        if (null == newVoucher) {
                            continue;
                        }
                        addList.add(newVoucher);
                    }*/
                    continue;
                }
            }
        }
        log.error("=================>" + addList.size());
        if (!CollectionUtils.isEmpty(addList)) {
            voucherService.saveBatch(addList);
        }
        AviatorEvaluator.removeFunction("ADD");
        return null;
    }

    /**
     * 每条数据转成map
     *
     * @param vo
     * @return
     */
    private Map<String, Object> getDataMap(Object vo) throws Exception {
        Map<String, Object> map = new HashMap<>();
        Class<?> clz = vo.getClass();
        Method[] methods = clz.getMethods();
        for (Method method : methods) {
            if (null == method || !method.getName().startsWith("get")) {
                continue;
            }
    /*        if ("getObject".equals(method.getName())) { //存放进去的实体对象的所有属性值
                Class<?> clzobj = vo.getClass();
                Method[] methodsobj = clzobj.getMethods();
                for (Method methodobj : methodsobj) {
                    if (null == method || !methodobj.getName().startsWith("get")) {
                        continue;
                    }
                    String key = methodobj.getName().substring(3).toUpperCase();
                    //通过反射的方法调用invoke获取属性值
                    //   map.put(key, String.valueOf(methodobj.invoke(vo.getObject())));
                }
                continue;
            }*/
            String key = method.getName().substring(3).toUpperCase();
            //通过反射的方法调用invoke获取属性值
            map.put(key, String.valueOf(method.invoke(vo)));
        }
        return map;
    }

    // 获取每个模板里表达式的值
    private Voucher getVoucher(VoucherTemplate template, Map<String, Object> mapData, Voucher bean) throws Exception {
        Voucher voucher = new Voucher();
        voucher.setNum(bean.getNum());
        voucher.setAccount(bean.getAccount());
        voucher.setId(DateUtil.generateUUID());
        voucher.setAccountId(bean.getAccount().getId());
        voucher.setFdate(DateUtil.strToLocalDate(bean.getSelfdate()));
        voucher.setSubjectId(template.getSubjectId());
        voucher.setDrandcr(template.getDrandcr());
        voucher.setSequence(template.getSequence());
        voucher.setFtype(template.getFtype());
        voucher.setRemark(template.getRemark());
        voucher.setAddTime(LocalDateTime.now());
        //获取金额和数量辅助项的表达式
        String moneyExp = template.getMoneyExpression();
        String amountExp = template.getAmountExpression();
        if (StringUtils.isNotBlank(moneyExp)) {
            Object objectMoney = AviatorEvaluator.execute(moneyExp.toUpperCase(), mapData);
            voucher.setMoney(null != objectMoney ? new BigDecimal(String.valueOf(objectMoney)) : BigDecimal.ZERO);
        }
        if (StringUtils.isNotBlank(amountExp)) {
            Object objectAmount = AviatorEvaluator.execute(amountExp.toUpperCase(), mapData);
            voucher.setAmount(null != objectAmount ? new BigDecimal(String.valueOf(objectAmount)) : BigDecimal.ZERO);
        }
        voucher.setPrice((null != voucher.getAmount() && voucher.getAmount().compareTo(BigDecimal.ZERO) != 0) ?
                BigDecimalUtil.divide(voucher.getMoney(), voucher.getAmount(), 4) : BigDecimal.ZERO);
        voucher.setCurrency(null != mapData.get("currency") ? String.valueOf(mapData.get("currency")) : "CNY");
        voucher.setFrate(null != mapData.get("frate") ?
                new BigDecimal(String.valueOf(mapData.get("frate"))) : new BigDecimal("1"));
        voucher.setSource(template.getSource());
        template.setProjectId(bean.getAccount().getProjectId());
        voucher.setSecuritiesCode(this.getAuxilary(template, mapData)); //证券代码
        return voucher;
    }

    /**
     * 获取是否有明细到证券的辅助项科目，存入凭证表的证券代码类型
     *
     * @param template
     * @throws Exception
     */
    private String getAuxilary(VoucherTemplate template, Map<String, Object> mapData) throws Exception {
       /* // 加载科目对应的辅助项信息
        SubjectAuxilary subjectAuxilary = new SubjectAuxilary();
        subjectAuxilary.setProjectId(template.getProjectId());
        subjectAuxilary.setSubjectId(template.getSubjectId());
        List<SubjectAuxilary> list = subjectAuxilaryService.querySubjectAdjustAuxilary(subjectAuxilary);
        if (CollectionUtils.isEmpty(list)) {
            return "";
        }
        for (SubjectAuxilary auxilary : list) {
            if (null == auxilary) {
                continue;
            }
            if (1 != auxilary.getRequired()) { // 是否启用
                continue;
            }
            if ("STOCKCODE".equals(auxilary.getDicCode())) { // 辅助项是字典配置的
                //在字典表里取对应的值
                return String.valueOf(mapData.get(auxilary.getCloumKey()));
            }
        }*/
        return "";
    }

    /**
     * 获取股票信息
     *
     * @param auxilaryCode
     * @param auxCode
     * @return
     */
    private String getOptionalAuxItem(String auxilaryCode, String auxCode) {
        FinanceAuxEnum financeAuxEnum = FinanceAuxEnum.getEnum(auxilaryCode);
        switch (financeAuxEnum) {
            case STOCKCODE:
                if ("600000".equals(auxCode)) {
                    return "浦发银行";
                } else {
                    return "蚂蚁金服";
                }
            default:
                break;
        }
        return null;
    }
}
